热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

发生|总数_ReactReact全家桶ahooks

篇首语:本文由编程笔记#小编为大家整理,主要介绍了ReactReact全家桶ahooks相关的知识,希望对你有一定的参考价值。文章目录

篇首语:本文由编程笔记#小编为大家整理,主要介绍了ReactReact全家桶ahooks相关的知识,希望对你有一定的参考价值。



文章目录


    • 1 ahooks简介
      • 1.1 什么是ahooks?
      • 1.2 ahooks的特点
      • 1.3 ahooks如何使用?

    • 2 ahooks API
      • 2.1 useRequest
      • 2.2 useAntdTable
      • 2.3 useBoolean
      • 2.4 useMemoizedFn
      • 2.5 useUrlState




1 ahooks简介


1.1 什么是ahooks?


  • ahooks 一套高质量可靠的 React Hooks 库
  • React 虽然提供基础的 hooks 函数,但在实际场景中,我们需要在基础函数上再封装 , ahooks 就满足了这个需求, 它的功能非常强大,拥有的 hooks 已经 60+ 。
  • ahooks官方文档

1.2 ahooks的特点


  • 易学易用
  • 支持 SSR( 服务器端渲染 )
    • React Hooks 在 SSR 场景下,普遍会碰到“DOM/BOM 缺失”、“useLayoutEffect 警告”两个问题。ahooks v3.0 彻底解决了这两个问题,你可以安心的将 ahooks 使用到 SSR 场景了。
  • 对输入输出函数做了特殊处理,避免闭包问题
    • 所有用户输入的函数,永远使用最新的一份( 通过useRef 进行实现 )
    • ahooks 所有的输出函数,引用地址都是不会变化的( 通过useMemoizedFn(ahooks 封装的)实现的,其实现也是通过 useRef实现 )
  • 包含大量提炼自业务的高级 Hooks
  • 包含丰富的基础 Hooks
  • 使用 TypeScript 构建,提供完整的类型定义文件

1.3 ahooks如何使用?

//引入
npm install --save ahooks
或 yarn add ahooks
//使用
import useRequest from 'ahooks'

2 ahooks API


2.1 useRequest

useRequest 是一个强大的异步数据管理的 Hooks,React 项目中的网络请求场景使用 useRequest就够了

useRequest 通过插件式组织代码,核心代码极其简单,并且可以很方便的扩展出更高级的功能。目前已有能力包括:


  • 自动请求/手动请求
  • 轮询
  • 防抖
  • 节流
  • 屏幕聚焦重新请求
  • 错误重试
  • loading delay
  • SWR(stale-while-revalidate)
  • 缓存

useRequest 的第一个参数是一个异步函数,在组件初次加载时,会自动触发该函数执行。同时自动管理该异步函数的 loading , data , error 等状态。

useRequest 的第二个参数可以为 options.manual = true ,若设置了这个参数,则 useRequest不会默认触发,需要通过run触发

data:service返回的数据

error:service抛出的异常

loading:service是否在执行

run:手动触发useRequest执行,参数会传递给service

params : 当次执行的 service 的参数数组。比如你触发了 run(1, 2, 3,则 params 等于 [1, 2, 3]

//第一个参数service是异步函数
const data, error, loading,run = useRequest(service,
manual: true//若设置了这个参数,则不会默认触发,需要通过run触发
defaulParams:[]//首次默认执行时,传递给 service 的参数
);

useRequest 提供了以下几个生命周期配置项,供你在异步函数的不同阶段做一些处理。


  • onBefore:请求之前触发
  • onSuccess:请求成功触发
  • onError:请求失败触发
  • onFinally:请求完成触发


案例


//按需引入antd组件库
import message from 'antd';
import React, useState from 'react';
import useRequest from 'ahooks';
//异步函数
function editUsername(username: string): Promise<void>
return new Promise((resolve, reject) &#61;>
setTimeout(() &#61;>
if (Math.random() > 0.5)
resolve();
else
reject(new Error(&#39;Failed to modify username&#39;));

, 1000);
);

export default () &#61;>
//添加输入框的内容状态
const [state, setState] &#61; useState(&#39;&#39;);
const loading, run &#61; useRequest(editUsername,
//手动触发
manual: true,
//四个声明周期函数
onBefore: (params) &#61;>
message.info(&#96;Start Request: $params[0]&#96;);
,
onSuccess: (result, params) &#61;>
setState(&#39;&#39;);
message.success(&#96;The username was changed to "$params[0]" !&#96;);
,
onError: (error) &#61;>
message.error(error.message);
,
onFinally: (params, result, error) &#61;>
message.info(&#96;Request finish&#96;);
,
);
return (
<div>
<input
//输入框发生改变时,将状态state设置为e.target.value
onChange&#61;(e) &#61;> setState(e.target.value)
//输入框的内容设置为state
value&#61;state
placeholder&#61;"Please enter username"
style&#61; width: 240, marginRight: 16
/>
//手动触发useRequest
<button disabled&#61;loading type&#61;"button" onClick&#61;() &#61;> run(state)>
loading ? &#39;Loading&#39; : &#39;Edit&#39;
</button>
</div>
);
;

API

const
//service是否正在执行
loading: boolean,
//service返回的数据
data?: TData,
//service抛出的异常
error?: Error,
//当次执行的service的参数数组。比如你触发了run(1, 2, 3)&#xff0c;则params等于[1, 2, 3]
params: TParams || [],
//手动触发service执行&#xff0c;参数会传递给service异常自动处理&#xff0c;通过onError反馈
run: (...params: TParams) &#61;> void,
//与run用法一致&#xff0c;但返回的是Promise&#xff0c;需要自行处理异常。
runAsync: (...params: TParams) &#61;> Promise<TData>,
//使用上一次的 params&#xff0c;重新调用 run
refresh: () &#61;> void,
//使用上一次的params&#xff0c;重新调用runAsync
refreshAsync: () &#61;> Promise<TData>,
//直接修改data
mutate: (data?: TData | ((oldData?: TData) &#61;> (TData | undefined))) &#61;> void,
//取消当前正在进行的请求
cancel: () &#61;> void,
&#61; useRequest<TData, TParams>(
//第一个参数为异步函数
service: (...args: TParams) &#61;> Promise<TData>,

//第二个参数
//如果设置为 true&#xff0c;则需要手动调用 run 或 runAsync 触发执行。
manual?: boolean,
//首次默认执行时&#xff0c;传递给service的参数
defaultParams?: TParams,
//service执行前触发
onBefore?: (params: TParams) &#61;> void,
//service resolve时触发
onSuccess?: (data: TData, params: TParams) &#61;> void,
//service reject时触发
onError?: (e: Error, params: TParams) &#61;> void,
//service 执行完成时触发
onFinally?: (params: TParams, data?: TData, e?: Error) &#61;> void,

);


useRequest还有很多功能具体请参照官网



2.2 useAntdTable

useAntdTable&#xff1a; 基于 useRequest 实现&#xff0c;封装了 Ant Design UI组件库中Table与Form联动逻辑。

const tableProps, search, loading &#61; useAntdTable(
async ( current: page, pageSize , formData) &#61;>
const data &#61; await getRoleList( page, pageSize, ...formData )
return
//data包含表格数据data和分页数据(page(当前页) pageSize(每页条数) toatl(数据总数) totalPage(页数总数))
...data,
list: data?.data

,

form

)
// tableProps包含 dataSource: data?.data 和 pagination: current: 1, pageSize: 10, total:

  • useAntdTable第一个参数为异步函数&#xff0c;它接收两个参数 :分页数据 current, pageSize, sorter, filters ,其中sorter,ilters用于表格分页、分类筛选等功能和表单数据(formData自定义)函数自动触发前会自动收集表单框中的数据&#xff0c;带入到接口入参中&#xff0c;格式key:value &#xff1b; 返回的数据结构为 total: number, list: Item[]
  • useAntdTable的第二个参数一般为form(挂载Form实例)&#xff0c;也可以增加默认参数或refreshDeps&#xff08;参数格式为数组[ ]&#xff09; &#xff0c;refreshDeps 变化&#xff0c;会重置 current 到第一页&#xff0c;并重新发起请求。
  • useAntdTable 返回tablePropssearch 字段&#xff0c;管理表格和表单。loading:异步函数(获取数据的过程)是否在执行,执行中为true,执行结束为false

Table 管理

useAntdTable 会自动管理 Table 分页数据&#xff0c;你只需要把返回的 tableProps 传递给 Table 组件就可以了

<Table columns&#61;columns rowKey&#61;"email" ...tableProps />

useAntdTable 如何和表单形成关联关系?


  • const form &#61;Form.useForm( ) 创建 Form 实例&#xff0c;用于管理所有数据状态

    //创建的form实例要给所需Form表单用
    <Form form&#61;form ></Form>

  • useAntdTable的第二个参数挂载form实例

Form 与 Table 联动

useAntdTable 接收 form 实例后&#xff0c;会返回 search 对象&#xff0c;用来处理表单相关事件。


  • search.type 支持 simpleadvance 两个表单切换
  • search.changeType&#xff0c;切换表单类型
  • search.submit 提交表单行为
  • search.reset 重置当前表单

初始化数据

useAntdTable 通过 defaultParams 设置初始化值&#xff0c;defaultParams 是一个数组&#xff0c;第一项为分页相关参数&#xff0c;第二项为表单相关数据。如果有第二个值&#xff0c;我们会帮您初始化表单&#xff01;

表单验证

表单提交之前&#xff0c;我们会调用 form.validateFields 来校验表单数据&#xff0c;如果验证不通过&#xff0c;则不会发起请求。

API

useRequest 所有参数和返回结果均适用于 useAntdTable&#xff0c;此处不再赘述。

type Data &#61; total: number; list: any[] ;
type Params &#61; [ current: number; pageSize: number, filter?: any, sorter?: any , [key: string]: any ];
//useAntdTable会返回tableProps和search字段&#xff0c;用于管理表格和表单
const
...,
//tableProp管理表格 Table组件需要的数据&#xff0c;直接透传给Table组件即可
tableProps:
//数据源
dataSource: any[];
//service是否在执行
loading: boolean;
//表格发生改变执行操作
onChange: (
pagination: any,
filters?: any,
sorter?: any,

) &#61;> void;
//分页数据
pagination:
//当前页
current: number;
//每页显示的数据
pageSize: number;
//总数据
total: number;
;
;
//search管理表单
search:
//当前表单类型
type: &#39;simple&#39; | &#39;advance&#39;;
//切换表单类型
changeType: () &#61;> void;
//提交表单
submit: () &#61;> void;
//重置当前表单
reset: () &#61;> void;
;
&#61; useAntdTable<TData extends Data, TParams extends Params>(
//异步函数
//service接收两个参数&#xff0c;第一个参数为分页数据 current, pageSize, sorter, filters &#xff0c;第二个参数为表单数据。
//service 返回的数据结构为 total: number, list: Item[] 。
service: (...args: TParams) &#61;> Promise<TData>,

...,
//接受的第二个参数
//Form实例
form?: any;
//默认表单类型
defaultType?: &#39;simple&#39; | &#39;advance&#39;;
//默认参数&#xff0c;第一项为分页数据&#xff0c;第二项为表单数据
// defaultParams: [
// current: 2, pageSize: 5 ,
// name: &#39;hello&#39;, email: &#39;abc&#64;gmail.com&#39;, gender: &#39;female&#39;
// ],
defaultParams?: TParams,
//默认分页数量
defaultPageSize?: numbe;
//refreshDeps 变化&#xff0c;会重置 current 到第一页&#xff0c;并重新发起请求。
refreshDeps?: any[];

);

2.3 useBoolean

useBoolean&#xff1a; 优雅的管理 boolean 状态的 Hook。

//state状态值和actions操作集合
//Actions toggle为切换state,set设置state,setTrue设置为true,setFals设置为false
const [ state, toggle, set, setTrue, setFalse ] &#61; useBoolean(
//传入的参数可选项&#xff0c;传入默认的状态值
defaultValue?: boolean
);

2.4 useMemoizedFn

持久化 function 的 Hook&#xff0c;理论上&#xff0c;可以使用 useMemoizedFn 完全代替 useCallback。

const memoizedFn &#61; useMemoizedFn(fn);

  • 参数&#xff1a;fn回调函数&#xff0c;引用地址永远不会变化的回调函数
  • 返回值&#xff1a;memoizedFn缓存版本的回调函数

const [name, setName] &#61; useState(&#39;xiaoMing&#39;)
const [age, seAge] &#61; useState(20)
// useCallback
// 在 state 变化时&#xff0c;memoFn 地址会变化
const memoFn &#61; useCallback(() &#61;>
console.log(&#39;name&#39;, name, &#39;age&#39;, age)
, [name, age])
// useMemoizedFn
// memoFn 地址永远不会变化
const memoFn &#61; useMemoizedFn(() &#61;>
console.log(&#39;name&#39;, name, &#39;age&#39;, age)
)

  • 在某些场景中&#xff0c;我们需要使用 useCallback 来记住一个函数&#xff0c;但是在第二个参数 deps 变化时&#xff0c;会重新生成函数&#xff0c;导致函数地址变化
  • 使用 useMemoizedFn&#xff0c;可以省略第二个参数 deps&#xff0c;同时保证函数地址永远不会变化&#xff0c;可以用于性能优化。
  • useMemoizedFn解决了由 hook 中的 deps 引起的闭包问题&#xff0c;同时保证了函数调用的准确性&#xff0c;实时性&#xff0c;保证函数调用可以拿到最新的值。

useMemoizedFn的实现

const callbackFn &#61; useCallback(() &#61;>
console.log(&#96;Current count is $count&#96;);
, [count]);

在上面的代码中&#xff0c;callbackFn 的 dep 必须包含 count&#xff0c;保证它被调用时能输出正确的 count&#xff0c;而不是错误的闭包值。但是这样的话&#xff0c;每次 count 发生变化时&#xff0c;callbackFn 本身的引用会变化&#xff0c;会触发依赖 callbackFn 的 ExpensiveTree 组件 重新render。在 ExpensiveTree 角度来看&#xff0c;其实这是一次多余的 render。
实际上&#xff0c;如果我们找到一种方法解决上面所说的问题&#xff0c;就实现了 useMemoizedFn 这个 hook&#xff0c;我们来看看需要解决的问题有哪些


  • callbackFn 的地址不能随 render 改变
  • 要同时保证 count 的实时更新
  • 并且 callbackFn 的引用地址不能变
  • 不需要添加 dep 依赖

接下来开始解决这些问题&#xff0c;如下&#xff1a;

function useMemoizedFn(fn)
// 这里可以拿到每次最新的 fn&#xff0c;并把它更新到 ref 中&#xff0c;这可以保证此 ref 能够持有最新的 fn 引用
const latestFn &#61; useRef(fn);
latestFn.current &#61; fn;
// 我们通过这个只初始化一次的 useRef 来构建一个函数调用外壳&#xff0c;保证这个外壳函数的引用不会发生变化
// 并且通过在内部持有最新函数的引用&#xff0c;来保证调用准确性
const memoizedFn &#61; useRef((...args) &#61;>
latestFn.current?.(...args);
);
return memoizedFn.current;

到这里&#xff0c;我们已经实现了 useMemoizedFn 的所有功能&#xff0c;简单来说&#xff0c;这个 hook 做的事情就是实时的维护函数的最新引用&#xff0c;并在适当的时候通过一个包装函数来调用它。


2.5 useUrlState

通过 url query 来管理 state 的 Hook。

npm i &#64;ahooksjs/use-url-state -S

该 Hooks 基于 react-router 的 useLocation & useHistory & useNavigate 进行 query 管理&#xff0c;一般获取路由参数使用该hook更加简便
使用该 Hooks 之前&#xff0c;你需要保证


  1. 你项目正在使用 react-router 5.x 或 6.x 版本来管理路由

  2. 独立安装了 &#64;ahooksjs/use-url-state

import useUrlState from &#39;&#64;ahooksjs/use-url-state&#39;;
const [state, setState] &#61; useUrlState(initialState, options);

  • initialState:初始状态
  • options:url配置
    navigateMode:状态变更时切换 history 的方法&#xff0c;默认push
    parseOptions:query-string parse 的配置
    stringifyOptions:query-string stringify 的配置
  • state:url query 对象
  • setState:用法同 useState&#xff0c;但 state 需要是 object

举个例子:

向路由组件传递search参数&#xff1a;
路由链接(携带参数)&#xff1a;详情
接收参数:

const search,setSearch &#61;useSearchParams()
const name &#61;search.get(&#39;name&#39;)
const id &#61;search.get(&#39;id&#39;)

使用useUrlState
const [query, setQuery] &#61; useUrlState(props, navigateMode: ‘replace’ );
query就直接可以取出name和id


推荐阅读
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • 本文介绍了JavaScript进化到TypeScript的历史和背景,解释了TypeScript相对于JavaScript的优势和特点。作者分享了自己对TypeScript的观察和认识,并提到了在项目开发中使用TypeScript的好处。最后,作者表示对TypeScript进行尝试和探索的态度。 ... [详细]
  • loader资源模块加载器webpack资源模块加载webpack内部(内部loader)默认只会处理javascript文件,也就是说它会把打包过程中所有遇到的 ... [详细]
  • 在本教程中,我们将看到如何使用FLASK制作第一个用于机器学习模型的RESTAPI。我们将从创建机器学习模型开始。然后,我们将看到使用Flask创建AP ... [详细]
  • 前言:原本纠结于Web模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中ev ... [详细]
  • ReactJSUIAnt设计空组件原文:https://w ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • python3 logging
    python3logginghttps:docs.python.org3.5librarylogging.html,先3.5是因为我当前的python版本是3.5之所 ... [详细]
  • 枚举使用枚举我们可以定义一些带名字的常量。使用枚举可以清晰地表达意图或创建一组有区别的用例。TypeScript支持数字的和基于字符串的枚举。数字枚举首先我们看看数字枚举,如果你使 ... [详细]
  • Node.js详细安装及环境配置
    1、下载安装根据自己电脑系统及位数选择,我这里选择windows64位.msi格式安装包(官网:https:odejs.orgzh-cndownload).msi和.zip格式区别 ... [详细]
author-avatar
780527a
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有